home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ChessMaster3000.thor by Troels Walsted Hansen ** $VER: ChessMaster3000.thor v1.20 (19.01.95) ** ** An ARexx script for playing a game of chess against another THOR- ** user through messages on a BBS. Please refer to the included file ** ChessMaster3000.doc for detailed information. */ options results /* needs THOR and bbsread.library functions */ p = ' ' || address() || ' ' || show('P',,) thorport = pos(' THOR.',p) if thorport > 0 then thorport = word(substr(p,thorport+1),1) else do say 'No THOR port found!' exit 10 end if ~show('p', 'BBSREAD') then do address command "run >nil: `GetEnv THOR/THORPath`bin/LoadBBSRead" "WaitForPort BBSREAD" end /* save out msgtext and determine whether to continue an old or start a new game */ address(thorport) THORTOFRONT SAVEMESSAGE CURRENT FILENAME '"T:ChessMaster3000.thor.temp"' NOHEADER NOANSI if ~open(ifh, 'T:ChessMaster3000.thor.temp', R) then do REQUESTNOTIFY TEXT '"Cannot open temporary file: T:ChessMaster3000.thor.temp"' BT '"_Ok"' exit end /* ***ChessMaster3000, round #1 */ newgame = 0 firstmove = 1 do until(pos('***ChessMaster3000', line) > 0) if eof(ifh) then do REQUESTNOTIFY TEXT '"Message contains no ChessMaster3000 data!"' BT '"_Ok"' REQUESTNOTIFY TEXT '"Start new game?"' BT '"_Yes|_No"' if(rc = 0 & result = 1) then do call close(ifh) /* initiate variables */ call NewGame() firstmove = 1 /* write all the data */ call WriteData() address(thorport) SHOWTEXT 'T:ChessMaster3000.thor.temp' /* move first turn */ call PlayMove() firstmove = 0 /* write all the data */ call WriteData() address(thorport) SHOWTEXT 'T:ChessMaster3000.thor.temp' /* post the file */ call PostMsg() signal exit end signal exit end line = readln(ifh) end firstmove = 0 /* read the rest of the chess info */ call ReadData() /* move the pieces etc. */ call PlayMove() /* write all the data to a file */ call WriteData() address(thorport) SHOWTEXT 'T:ChessMaster3000.thor.temp' /* initiate all variables from message info */ address(thorport) CURRENTMSG stem MSG address(bbsread) READBRMESSAGE bbsname '"'MSG.BBSNAME'"' confname '"'MSG.CONFNAME'"' msgnr '"'MSG.MSGNR'"' headstem HEAD textstem TEXT EVENT.TYPE = 1 /* replymsg */ EVENT.TONAME = HEAD.FROMNAME EVENT.SUBJECT = HEAD.SUBJECT EVENT.CONFERENCE = MSG.CONFNAME EVENT.REFNR = MSG.MSGNR EVENT.REFORGINALNR = HEAD.ORGINALNR /* Not needed? EVENT.REFID = HEAD.REFID EVENT.TOADDR = TEXT.REPLYADDR */ /* post the file as a reply to the current message */ call PostMsg() signal exit NewGame: /* initiate all variables otherwise read from the message text */ roundnumber = 0 newgame = 1 pos.1.8 = ' #C# '; pos.2.8 = ' #N# '; pos.3.8 = ' #B# '; pos.4.8 = ' #Q# '; pos.5.8 = ' #K# '; pos.6.8 = ' #B# '; pos.7.8 = ' #N# '; pos.8.8 = ' #C# ' pos.1.7 = ' #P# '; pos.2.7 = ' #P# '; pos.3.7 = ' #P# '; pos.4.7 = ' #P# '; pos.5.7 = ' #P# '; pos.6.7 = ' #P# '; pos.7.7 = ' #P# '; pos.8.7 = ' #P# ' do y=6 to 3 by -1 do x=1 to 8 pos.x.y = ' ' end end pos.1.2 = ' P '; pos.2.2 = ' P '; pos.3.2 = ' P '; pos.4.2 = ' P '; pos.5.2 = ' P '; pos.6.2 = ' P '; pos.7.2 = ' P '; pos.8.2 = ' P ' pos.1.1 = ' C '; pos.2.1 = ' N '; pos.3.1 = ' B '; pos.4.1 = ' Q '; pos.5.1 = ' K '; pos.6.1 = ' B '; pos.7.1 = ' N '; pos.8.1 = ' C ' blacklosses = '' whitelosses = '' /* initiate all variables otherwise read from the message header data */ EVENT.TYPE = 0 /* entermsg */ address(bbsread) GETBBSLIST stem BBSLIST if(rc ~= 0) then do address(thorport) REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"' signal exit end address(thorport) REQUESTLIST instem BBSLIST title '"Select BBS:"' SIZEGADGET if(rc ~= 0) then signal exit else MSG.BBSNAME = result address(bbsread) GETCONFLIST '"'MSG.BBSNAME'"' CONFLIST if(rc ~= 0) then do address(thorport) REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"' signal exit end address(thorport) REQUESTLIST instem CONFLIST title '"Select conf:"' SIZEGADGET if(rc ~= 0) then signal exit else EVENT.CONFERENCE = result REQUESTSTRING TITLE '"Please enter subject of message:"' BT '"_Ok|_Cancel"' ID '"ChessMaster3000"' MAXCHARS 100 EVENT.SUBJECT = result if(rc ~= 0 | EVENT.SUBJECT = "") then signal exit do forever REQUESTSTRING TITLE '"Please enter the name of your opponent:"' BT '"_Ok|_Cancel "' MAXCHARS 200 if(rc ~= 0) then signal exit EVENT.TONAME = result if(upper(EVENT.TONAME) ~= "ALL") then do address(bbsread) SEARCHBRUSER bbsname '"'MSG.BBSNAME'"' stem USERS search '"'EVENT.TONAME'"' name address alias suggestusersstem SUG if(rc ~= 0) then signal exit if(result > 0) then do drop LIST. drop USERTAGS. LIST.COUNT = USERS.COUNT do n = 1 to USERS.COUNT LIST.n.USERNR = USERS.n.USERNR address(bbsread) READBRUSER bbsname '"'MSG.BBSNAME'"' usernr USERS.n.USERNR tagsstem USERTAGS if(rc ~= 0) then signal exit LIST.n = USERTAGS.NAME if(symbol("USERTAGS.ADDRESS") = "VAR") then LIST.n.ADDRESS = USERTAGS.ADDRESS end address(thorport) REQUESTLIST instem LIST title '"Select user:"' if(rc ~= 0) then do if(rc ~= 5) then REQUESTNOTIFY TEXT '"'THOR.LASTERROR'"' BT '"_Ok"' signal exit end EVENT.TONAME = result do n = 1 to LIST.COUNT if(LIST.n = EVENT.TONAME) then EVENT.TOADDR = LIST.n.ADDRESS end leave end else do if(symbol("SUG.COUNT") = "VAR") then do address(thorport) REQUESTLIST instem SUG title '"Select user:"' if(rc ~= 0) then do if(rc ~= 5) then REQUESTNOTIFY TEXT '"'THOR.LASTERROR'"' BT '"_Ok"' signal exit end EVENT.TONAME = result do n = 1 to SUG.COUNT if(SUG.n = EVENT.TONAME) then usernumber = SUG.n.USERNR end drop USERTAGS. address(bbsread) READBRUSER bbsname '"'MSG.BBSNAME'"' usernr usernumber tagsstem USERTAGS if(rc ~= 0) then signal exit if(symbol("USERTAGS.ADDRESS") = "VAR") then EVENT.TOADDR = USERTAGS.ADDRESS leave end else do address(thorport) REQUESTNOTIFY TEXT '"No matching users found, try again?"' BT '"_Ok|_Cancel"' if(rc ~= 0) then signal exit if(result = 0) then signal exit end end end else signal exit /* doesn't work with ALL */ end blackplayer = EVENT.TONAME RETURN ReadData: roundnumber = substr(line, lastpos('#', line)+1) /* Black: Matthias Bartosik White: Troels Walsted_Hansen */ call readln(ifh) blackplayer = substr(readln(ifh), 8) whiteplayer = substr(readln(ifh), 8) /* Status: White Pawn at H1 exchanged for Bishop +---+---+---+---+---+---+---+---+ */ do 4; call readln(ifh); end /* 8 | #C# | #N# | #B# | #Q# | #K# | #B# | #N# | #C# | +---+-^-+---+-^-+---+-^-+---+-^-+ 7 | #P# | #P# | #P# | #P# | #P# | #P# | #P# | #P# | +-^-+---+-^-+---+-^-+---+-^-+---+ 6 | | | | | | | | | +---+-^-+---+-^-+---+-^-+---+-^-+ 5 | | | | | | | | | +-^-+---+-^-+---+-^-+---+-^-+---+ 4 | | | | | | | | | +---+-^-+---+-^-+---+-^-+---+-^-+ 3 | | | | | | | | | +-^-+---+-^-+---+-^-+---+-^-+---+ 2 | P | P | P | P | P | P | P | P | +---+-^-+---+-^-+---+-^-+---+-^-+ 1 | C | N | B | Q | K | B | N | C | +-^-+---+-^-+---+-^-+---+-^-+---+ a b c d e f g h Black losses: */ line.8 = readln(ifh); call readln(ifh) line.7 = readln(ifh); call readln(ifh) line.6 = readln(ifh); call readln(ifh) line.5 = readln(ifh); call readln(ifh) line.4 = readln(ifh); call readln(ifh) line.3 = readln(ifh); call readln(ifh) line.2 = readln(ifh); call readln(ifh) line.1 = readln(ifh) do 4; call readln(ifh); end /* #C#, #Q# White losses: B, P, Q */ blacklosses = readln(ifh) do 2; call readln(ifh); end whitelosses = readln(ifh) call close(ifh) /* parse the input */ do y=1 to 8 line.y = delstr(line.y, 1, 6) do x=1 to 8 pos.x.y = substr(line.y, 1, pos('|', line.y)-1) line.y = delstr(line.y, 1, pos('|', line.y)) end end RETURN PlayMove: /* determine who the current player is */ address(thorport) CURRENTBBS stem CURRENT if(rc ~= 0) then do address(thorport) REQUESTNOTIFY TEXT '"'THOR.LASTERROR'"' BT '"_Ok"' signal exit end address(bbsread) GETBBSDATA bbsname '"'CURRENT.BBSNAME'"' stem BBSDATA if(rc ~= 0) then do address(thorport) REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"' signal exit end if(BBSDATA.USERNAME = '') then do GETGLOBALDATA stem GLOBALDATA if(rc ~= 0) then do address(thorport) REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"' signal exit end if(GLOBALDATA.USERNAME = '') then signal exit else username = GLOBALDATA.USERNAME end else username = BBSDATA.USERNAME if(newgame) then whiteplayer = username select when(username = blackplayer) then do color = 'Black' othercolor = 'White' end when(username = whiteplayer) then do color = 'White' othercolor = 'Black' end otherwise signal exit end /* ask user to specify move */ exchangepawn = 0 longcastle = 0 shortcastle = 0 passant = 0 address(thorport) REQUESTSTRING TITLE '"ChessMaster3000"' BODY '"' || color || ' player enter your move\non the form ''xyxy''.' || '"' BT '"_Ok|_Special move|_Cancel"' MAXCHARS 4 if(rc ~= 0) then signal exit /* normal move */ if(result ~= '') then do origmovestr = upper(result) movestr = translate(origmovestr, '12345678', 'ABCDEFGH') fromxpos = substr(movestr, 1, 1); fromypos = substr(movestr, 2, 1) toxpos = substr(movestr, 3, 1); toypos = substr(movestr, 4, 1) /* verify the integrity of the coordinates */ select when(fromxpos > 8 | fromxpos < 1) then errormsg = 'FROM x-coordinate out of range.' when(fromypos > 8 | fromypos < 1) then errormsg = 'FROM y-coordinate out of range.' when(toxpos > 8 | toxpos < 1) then errormsg = 'TO x-coordinate out of range.' when(toypos > 8 | toypos < 1) then errormsg = 'TO y-coordinate out of range.' when(pos.fromxpos.fromypos = ' ') then errormsg = 'Invalid FROM coordinates, no chess piece found.' when(left(strip(pos.fromxpos.fromypos, B), 1) = '#' & color = 'White' | left(strip(pos.fromxpos.fromypos, B), 1) ~= '#' & color = 'Black') then errormsg = 'Invalid FROM coordinates, trying to\nmove other player''s chess piece.' when(pos.toxpos.toypos ~= ' ' & left(strip(pos.toxpos.toypos, B), 1) ~= '#' & color = 'White' | left(strip(pos.toxpos.toypos, B), 1) = '#' & color = 'Black') then errormsg = 'TO square is occupied by your own piece.' otherwise errormsg = '' end if(errormsg ~= '') then do address(thorport) REQUESTNOTIFY TEXT '"'errormsg'"' BT '"_Ok"' signal exit end /* determine whether an enemy piece has been beaten */ frompiece = compress(pos.fromxpos.fromypos, '# ') topiece = compress(pos.toxpos.toypos, '# ') if(pos.toxpos.toypos ~= ' ') then do if(topiece = 'K') then do address(thorport) do 50; BEEP; end REQUESTNOTIFY TEXT '"You have won the game!"' BT '"H_ooya!"' /* gotta post a fancy message here */ signal exit end if(color = 'Black') then whitelosses = whitelosses || ', ' || strip(pos.toxpos.toypos, B) else blacklosses = blacklosses || ', ' || strip(pos.toxpos.toypos, B) select when(left(blacklosses, 1) = ',') then blacklosses = substr(blacklosses, 3) when(left(whitelosses, 1) = ',') then whitelosses = substr(whitelosses, 3) otherwise nop end end else anyonebeaten = 'FALSE' /* move the piece to the TO square and clear the FROM square */ pos.toxpos.toypos = pos.fromxpos.fromypos pos.fromxpos.fromypos = ' ' end else /* special move */ do address(thorport) REQUESTNOTIFY TEXT '"Select special move:"' BT '"_Exchange Pawn|C_astle|_Passant|_Cancel"' if(rc ~= 0) then signal exit select when(result = 0) then signal exit /* Cancel */ when(result = 1) then /* Exchange Pawn */ do exchangepawn = 1 if(color = 'Black') then y = 1 else y = 8 availpawn.count = 0 do x=1 to 8 if(compress(pos.x.y, '# ') = 'P') then do availpawn.count = availpawn.count+1 k = availpawn.count availpawn.k = translate(x, 'ABCDEFGH', '12345678') || y end end if(availpawn.count = 0) then do address(thorport) REQUESTNOTIFY TEXT '"No Pawn-exchanging is possible."' BT '"_Ok"' signal exit end if(availpawn.count ~= 1) then do /* change to REQUESTNOTIFY !? */ address(thorport) REQUESTLIST TITLE '"Choose one set of coordinates"' instem availpawn SIZEGADGET if(rc ~= 0) then signal exit pawncoord = result end else pawncoord = availpawn.1 address(thorport) REQUESTNOTIFY TEXT '"Select new chess piece:"' BT '"_Queen|_Bishop|K_night|_Castle"' if(rc ~= 0) then signal exit select when(result = 0) then signal exit when(result = 1) then frompiece = 'Q' when(result = 2) then frompiece = 'B' when(result = 3) then frompiece = 'N' when(result = 4) then frompiece = 'C' otherwise frompiece = 'P' end if(color = 'Black') then styledfrompiece = ' #' || frompiece || '# ' else styledfrompiece = ' ' || frompiece || ' ' x = translate(left(pawncoord, 1), '12345678', 'ABCDEFGH') y = right(pawncoord, 1) pos.x.y = styledfrompiece end when(result = 2) then /* Castle */ do if(color = 'Black') then y = 8 else y = 1 if(compress(pos.1.y, '# ') = 'C' & pos.2.y = ' ' & pos.3.y = ' ' & pos.4.y = ' ' & compress(pos.5.y, '# ') = 'K') then longcastle = 1 if(compress(pos.5.y, '# ') = 'K' & pos.6.y = ' ' & pos.7.y = ' ' & compress(pos.8.y, '# ') = 'C') then shortcastle = 1 if(longcastle = 0 & shortcastle = 0) then do address(thorport) REQUESTNOTIFY TEXT '"You cannot perform a castling."' BT '"_Ok"' signal exit end gadstr = '' if(longcastle = 1 & shortcastle = 1) then do address(thorport) REQUESTNOTIFY TEXT '"Select which kind of castling:"' BT '"_Long|_Short|_Cancel"' if(rc ~= 0) then signal exit if(result = 1) then shortcastle = 0 else longcastle = 0 end /* style 'em */ if(color = 'Black') then do styledking = ' #K# ' styledcastle = ' #C# ' end else do styledking = ' K ' styledcastle = ' C ' end select when(longcastle = 1) then do pos.1.y = ' '; pos.5.y = ' ' pos.3.y = styledking; pos.4.y = styledcastle end when(shortcastle = 1) then do pos.8.y = ' '; pos.5.y = ' ' pos.7.y = styledking; pos.6.y = styledcastle end otherwise signal exit end end when(result = 3) then /* Passant */ do passant = 1 /* beating 'en passant' may happen only if two opponent pawns are standing next to each other on either y=5 | y=4. */ if(color = 'Black') then y = 4 else y = 5 availpassant.count = 0 do x=1 to 8 k = x+1 if(pos.x.y = ' P ' & pos.k.y = ' #P# ' | pos.x.y = ' #P# ' & pos.k.y = ' P ') then do /* determine which one belongs to the current player */ select when(pos.x.y = ' P ' & color = 'White') then do passantkillercolor = 'White' passantvictimcolor = 'Black' passantkillerx = x passantvictimx = k end when(pos.k.y = ' P ' & color = 'White') then do passantkillercolor = 'White' passantvictimcolor = 'Black' passantkillerx = k passantvictimx = x end when(pos.x.y = ' #P# ' & color = 'Black') then do passantkillercolor = 'Black' passantvictimcolor = 'White' passantkillerx = x passantvictimx = k end when(pos.k.y = ' #P# ' & color = 'Black') then do passantkillercolor = 'Black' passantvictimcolor = 'White' passantkillerx = k passantvictimx = x end otherwise signal exit end /* determine whether the appropriate squares are open */ if(passantkillercolor = 'Black' & pos.passantvictimx.2 = ' ' & pos.passantvictimx.3 = ' ' | passantkillercolor = 'White' & pos.passantvictimx.6 = ' ' & pos.passantvictimx.7 = ' ') then do availpassant.count = availpassant.count+1 j = availpassant.count availpassant.j = translate(passantkillerx, 'ABCDEFGH', '12345678') || y || ' beating ' || translate(passantvictimx, 'ABCDEFGH', '12345678') || y end end end if(availpassant.count = 0) then do address(thorport) REQUESTNOTIFY TEXT '"No passant opportunities available."' BT '"_Ok"' signal exit end if(availpassant.count ~= 1) then do address(thorport) REQUESTLIST TITLE '"Choose one scenario:"' instem availpassant SIZEGADGET if(rc ~= 0) then signal exit passantcoord = result end else passantcoord = availpassant.1 toxpos = translate(substr(passantcoord, 12, 1), '12345678', 'ABCDEFGH') if(color = 'Black') then whitelosses = whitelosses || ', ' || strip(pos.toxpos.y, B) else blacklosses = blacklosses || ', ' || strip(pos.toxpos.y, B) select when(left(blacklosses, 1) = ',') then blacklosses = substr(blacklosses, 3) when(left(whitelosses, 1) = ',') then whitelosses = substr(whitelosses, 3) otherwise nop end /* clear the TO square */ pos.toxpos.y = ' ' passantcoord = right(passantcoord, 2) end otherwise signal exit /* just in case */ end end roundnumber = roundnumber+1 RETURN WriteData: /* write the whole thing to a temp file */ call open(ofh, 'T:ChessMaster3000.thor.temp', W) call writeln(ofh, '***ChessMaster3000, round #' || roundnumber) call writeln(ofh, '') call writeln(ofh, 'Black: ' || blackplayer) if(firstmove) then whiteplayer = 'You.' call writeln(ofh, 'White: ' || whiteplayer) call writeln(ofh, '') select when(topiece = 'K') then str = ' King' when(topiece = 'Q') then str = ' Queen' when(topiece = 'C') then str = ' Castle' when(topiece = 'N') then str = ' Knight' when(topiece = 'B') then str = ' Bishop' when(topiece = 'P') then str = ' Pawn' otherwise str = ' Unknown' end if(anyonebeaten ~= 'FALSE') then beatenstr = ' beating ' || othercolor || str else beatenstr = '' select when(frompiece = 'K') then str = ' King ' when(frompiece = 'Q') then str = ' Queen ' when(frompiece = 'C') then str = ' Castle ' when(frompiece = 'N') then str = ' Knight ' when(frompiece = 'B') then str = ' Bishop ' when(frompiece = 'P') then str = ' Pawn ' otherwise str = ' Unknown ' end select when(firstmove) then statstr = 'Status: Waiting for your first move.' when(exchangepawn) then statstr = 'Status: ' || color || ' Pawn at ' || pawncoord || ' exchanged for' || str when(longcastle) then statstr = 'Status: ' || color || ' performed a long castling' when(shortcastle) then statstr = 'Status: ' || color || ' performed a short castling' when(passant) then statstr = 'Status: ' || color || ' Pawn beat a ' || othercolor || ' Pawn en passant at ' || passantcoord otherwise statstr = 'Status: ' || color || str || 'from ' || left(origmovestr, 2) || ' to ' || right(origmovestr, 2) || beatenstr end call writeln(ofh, statstr) call writeln(ofh, '') call writeln(ofh, ' +---+---+---+---+---+---+---+---+') do y=8 to 1 by -1 call writeln(ofh, ' ' || y || ' |' || pos.1.y || '|' || pos.2.y || '|' || pos.3.y || '|' || pos.4.y || '|' || pos.5.y || '|' || pos.6.y || '|' || pos.7.y || '|' || pos.8.y || '|') if(y//2 = 0) then str = ' +---+-^-+---+-^-+---+-^-+---+-^-+' else str = ' +-^-+---+-^-+---+-^-+---+-^-+---+' call writeln(ofh, str) end call writeln(ofh, ' a b c d e f g h') call writeln(ofh, '') call writeln(ofh, 'Black losses:') call writeln(ofh, blacklosses) call writeln(ofh, '') call writeln(ofh, 'White losses:') call writeln(ofh, whitelosses) call writeln(ofh, '') call writeln(ofh, 'K = King B = Bishop C = Castle') call writeln(ofh, 'Q = Queen N = Knight P = Pawn') call close(ofh) RETURN PostMsg: address(bbsread) UNIQUEMSGFILE bbsname '"'MSG.BBSNAME'"' stem UNIQUEFILE if(rc ~= 0) then do address(thorport) REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"' signal exit end address command 'copy >nil: T:ChessMaster3000.thor.temp TO ' || UNIQUEFILE.NAME EVENT.MSGFILE = UNIQUEFILE.FILEPART address(bbsread) WRITEBREVENT bbsname '"'MSG.BBSNAME'"' event EVENT.TYPE stem EVENT if(rc ~= 0) then do address(thorport) REQUESTNOTIFY TEXT '"'BBSREAD.LASTERROR'"' BT '"_Ok"' signal exit end address(thorport) REQUESTNOTIFY TEXT '"Edit message?"' BT '"_Yes|_No"' if(result = 1) then STARTEDITOR FILE '"'UNIQUEFILE.NAME'"' RETURN signal exit: address command 'delete T:ChessMaster3000.thor.temp quiet' exit